package info.monkeyws.AutoRinger;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.media.AudioManager;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.provider.ContactsContract.PhoneLookup;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.format.Time;

public class AutoRingerService extends Service {
	private int interval;
	private int quiet_threshold;
	private boolean phone_state_idle = true;
	
	private SharedPreferences pref;
	private Editor editor;
	private Handler handler;
	private AudioManager audiomanager;
	private TelephonyManager telManager;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		//Telephone state listener to avoid sampling volume when making a phone call
		telManager = (TelephonyManager)	getSystemService(TELEPHONY_SERVICE);
		telManager.listen(new TelListener(), PhoneStateListener.LISTEN_CALL_STATE);
		
		audiomanager = (AudioManager) getSystemService(AUDIO_SERVICE);

		pref = PreferenceManager.getDefaultSharedPreferences(this);
        editor = pref.edit();
        editor.putBoolean("service_running", true);
		editor.commit();		
		
		interval = pref.getInt("time_interval", Settings.DEFAULT_TIME_INTERVAL) * 60000;
		quiet_threshold = pref.getInt("quiet_threshold", Settings.DEFAULT_QUIET_THRESHOLD);
		
		//Change interval according to battery status
		BroadcastReceiver battReceiver = new BroadcastReceiver() {

			@Override
			public void onReceive(Context context, Intent intent) {
				// TODO Auto-generated method stub				
				if (true == pref.getBoolean("auto_time_interval", Settings.DEFAULT_AUTO_TIME_INTERVAL)){
					int max_level;
					int now_level;
					
					if (-1 == (max_level = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1))){
						return;
					}
					
					if (-1 == (now_level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1))){
						return;
					}				
					
					if (((float)now_level / max_level) * 100 < Settings.PERCENT_LOW_BATTERY){ //low battery
						editor.putInt("time_interval", Settings.TIME_INTERVAL_LOW_BATTERY);	
					}else{
						editor.putInt("time_interval", Settings.DEFAULT_TIME_INTERVAL);
					}			
				}
			}			
		};
		
		IntentFilter battFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
		registerReceiver(battReceiver, battFilter);
		
		handler = new Handler();
		handler.removeCallbacks(ChangeVolume);
		handler.postDelayed(ChangeVolume, 5000);		
	}
	
	private Runnable ChangeVolume = new Runnable(){
		//************************************************************
		//Core Algorithm
		//************************************************************
		@Override
		public void run() {
			// TODO Auto-generated method stub
			
			//Do not sample 
			if (false == phone_state_idle){
				handler.postDelayed(this, Settings.TIME_INTERVAL_WHEN_BUSY);
				return;
			}
				
			
			int index = 0; //The index to adjust the ringer volume.
			
			if (pref.getBoolean("enable_sleep_time", Settings.DEFAULT_ENABLE_SLEEP_TIME) == true) {
				//Sleep_time_function
				Time time = new Time();				
				time.setToNow();
				int h = time.hour;
				int m = time.minute;
				
				int bh = pref.getInt("sleep_begin_hour", Settings.DEFAULT_SLEEP_BEGIN_HOUR);
				int bm = pref.getInt("sleep_begin_minute", Settings.DEFAULT_SLEEP_BEGIN_MINUTE);
				int eh = pref.getInt("sleep_end_hour", Settings.DEFAULT_SLEEP_END_HOUR);
				int em = pref.getInt("sleep_end_minute", Settings.DEFAULT_SLEEP_END_MINUTE);
				
				if (bh > eh || (bh == eh && bm >= em)){
					if ((h > bh || (h == bh && m >= bm)) || 
					(h < eh || (h == eh && m <= em))){						
						audiomanager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
						return;
					}
				}else{
					if ((h > bh || (h == bh && m >= bm)) ||
						(h < eh || (h == eh && m <= em))){
						audiomanager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
						return;
					}
				}				
				
			}
			//Change the ringer volume according to the mic volume and missing calls
			int max_volume = audiomanager.getStreamMaxVolume(AudioManager.STREAM_RING);
			int volume = MicVolume.getVolume() - quiet_threshold;
			if (volume < Settings.DEFAULT_MIN_THRESHOLD){
				index = 0;
			}else if (volume > Settings.DEFAULT_MAX_THRESHOLD){
				index = 100;
			}else{
				index = (int)((float)volume / (float)(Settings.DEFAULT_MAX_THRESHOLD - Settings.DEFAULT_MIN_THRESHOLD)* 100);
			}
			
			if (pref.getBoolean("avoid_missing_calls", Settings.DEFAULT_AVOID_MISSING_CALLS)){
				//Index adjusted by missing calls
									
				Cursor c = getContentResolver().query(
				    CallLog.Calls.CONTENT_URI,
				    null, null, null,
				    CallLog.Calls.DATE + " DESC");
									
				
				int TypeColume = c.getColumnIndex(CallLog.Calls.TYPE);
									
				c.moveToFirst();					
				
				if (CallLog.Calls.MISSED_TYPE == c.getInt(TypeColume)){
					index += Settings.INDEX_MISSED_CALL;						
				}													
				
			}
			
			//Change the ringer volume according to index
			if (index == 0){
				audiomanager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
			}else if (index >= 100){
				audiomanager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
				audiomanager.setStreamVolume(AudioManager.STREAM_RING, max_volume, 0);
			}else{
				int ringer_index = (int)((float)index / 100 * max_volume);
				audiomanager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
				audiomanager.setStreamVolume(AudioManager.STREAM_RING, ringer_index, 0);
			}			
							
			handler.postDelayed(this, interval);			
		}
		
	};
	
	private class TelListener extends PhoneStateListener {

		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			super.onCallStateChanged(state, incomingNumber);
			// TODO Auto-generated method stub
			//Set the IDLE tag
			if (TelephonyManager.CALL_STATE_IDLE == state){
				phone_state_idle = true;
			}else{
				phone_state_idle = false;
			}
			
			//If the number is starred, it is a VIP call
			if (true == pref.getBoolean("always_ring_vip", Settings.DEFAULT_ALWAYS_RING_VIP)){				
				if (TelephonyManager.CALL_STATE_RINGING == state){								
					Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(incomingNumber));
					Cursor c = getContentResolver().query(uri, 
							new String[]{PhoneLookup.STARRED},
							null, null,	null);
					
					c.moveToFirst();
					while (!c.isAfterLast()){
						if (1 == c.getInt(0)){
							//set the max volume
							int max_volume = audiomanager.getStreamMaxVolume(AudioManager.STREAM_RING);
							audiomanager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
							audiomanager.setStreamVolume(AudioManager.STREAM_RING, max_volume, 0);
							handler.postDelayed(ChangeVolume, Settings.TIME_INTERVAL_WHEN_BUSY);
							break;
						}else{
							c.moveToNext();
						}
					}								
				}
			}
			
		}
		
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		editor.putBoolean("service_running", false);
		editor.commit();
		handler.removeCallbacks(ChangeVolume);
		
		super.onDestroy();
	}
}
